﻿using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.Blazor.SystemModule;
using EasyXaf.ExcelImporters;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

namespace EasyXaf.Blazor.ExcelImporters;

public class BlazorImportExcelController : ViewController<ListView>
{
    private ImportExcelController _importExcelController;

    protected override void OnActivated()
    {
        base.OnActivated();

        var importExcelController = Frame.GetController<ImportExcelController>();
        if (importExcelController != null && importExcelController.Active)
        {
            _importExcelController = importExcelController;
            importExcelController.ImportAction.Execute += ImportAction_Execute;
        }
    }

    protected override void OnDeactivated()
    {
        if (_importExcelController != null)
        {
            _importExcelController.ImportAction.Execute -= ImportAction_Execute;
        }

        base.OnDeactivated();
    }

    private Type GetExcelImporterTempFileType()
    {
        var baseType = typeof(IExcelImporterTempFile);
        var type = Application.TypesInfo.PersistentTypes
            .Where(t => t.IsPersistent)
            .Select(t => t.Type)
            .Where(t => baseType.IsAssignableFrom(t))
            .FirstOrDefault();
        return type ?? throw new Exception($"没有找到基于{baseType.Name}接口实现的业务类");
    }

    private void DownloadExcelFile(IObjectSpace objectSpace, IExcelImporterTempFile excelImporterTempFile)
    {
        var fileUrlServiceType = typeof(SystemBlazorModule).Assembly.GetType("DevExpress.ExpressApp.Blazor.Services.IFileUrlService");
        var fileUrlService = Application.ServiceProvider.GetService(fileUrlServiceType);
        var getFileUrlMethodInfo = fileUrlService.GetType().GetMethod("GetFileUrl", BindingFlags.Public | BindingFlags.Instance);
        var fileUrl = (string)getFileUrlMethodInfo.Invoke(fileUrlService, new object[] { objectSpace, excelImporterTempFile, "ExcelFile", null });
        Application.ServiceProvider.GetService<NavigationManager>().NavigateTo(fileUrl, forceLoad: true);
    }

    private void ImportExcel(IModelImporting importingModel)
    {
        var excelImporterTempFileType = GetExcelImporterTempFileType();
        var objectSpace = Application.CreateObjectSpace(excelImporterTempFileType);
        var excelImporterTempFile = (IExcelImporterTempFile)objectSpace.CreateObject(excelImporterTempFileType);
        var view = Application.CreateDetailView(objectSpace, excelImporterTempFile);
        Application.ShowViewStrategy.ShowViewInPopupWindow(view, () =>
        {
            if (!excelImporterTempFile.IsEmpty)
            {
                try
                {
                    var excelImporter = new ExcelImporter(View, Application, importingModel);
                    using var excelStream = new MemoryStream();
                    excelImporterTempFile.SaveToStream(excelStream);
                    if (excelImporter.ImportExcel(excelStream))
                    {
                        View.RefreshDataSource();
                        Application.ShowViewStrategy.ShowMessage("导入Excel成功", InformationType.Info);
                    }
                    else
                    {
                        excelImporterTempFile.FileName = $"{importingModel.GetCaption()}_导入失败.xlsx";
                        excelImporterTempFile.FileContent = excelStream.ToArray();
                        objectSpace.CommitChanges();
                        DownloadExcelFile(objectSpace, excelImporterTempFile);
                        Application.ShowViewStrategy.ShowMessage("导入Excel失败，详细请查看Excel文件", InformationType.Error);
                    }
                }
                catch (Exception ex)
                {
                    Application.ShowViewStrategy.ShowMessage($"导入Excel失败，{ex.Message}", InformationType.Error);
                }
            }
        });
    }

    private void ExportExcelTemplate(IModelImporting importingModel)
    {
        try
        {
            var importExcelTemplate = new ImportExcelTemplate(View, Application, importingModel);
            using var templateStream = importExcelTemplate.GenerateTemplate();
            using var excelImportTempFileStream = new MemoryStream();
            templateStream.Seek(0, SeekOrigin.Begin);
            var buffer = new byte[1024];
            while (templateStream.Read(buffer, 0, buffer.Length) > 0)
            {
                excelImportTempFileStream.Write(buffer, 0, buffer.Length);
            }
            var excelImporterTempFileType = GetExcelImporterTempFileType();
            using var objectSpace = Application.CreateObjectSpace(excelImporterTempFileType);
            var excelImporterTempFile = (IExcelImporterTempFile)objectSpace.CreateObject(excelImporterTempFileType);
            excelImporterTempFile.InitFile($"{importingModel.GetCaption()}_导入模板.xlsx", excelImportTempFileStream.ToArray());
            objectSpace.CommitChanges();
            DownloadExcelFile(objectSpace, excelImporterTempFile);
            Application.ShowViewStrategy.ShowMessage("导出Excel模板成功", InformationType.Info);
        }
        catch (Exception ex)
        {
            throw new UserFriendlyException($"生成Excel模板失败，{ex.Message}");
        }
    }

    private void ImportAction_Execute(object sender, SingleChoiceActionExecuteEventArgs e)
    {
        if (e.SelectedChoiceActionItem?.Id?.ToString() == "ImportExcel")
        {
            if (e.SelectedChoiceActionItem.Data is IModelImporting importingModel)
            {
                ImportExcel(importingModel);
            }
        }
        else if (e.SelectedChoiceActionItem?.Id?.ToString() == "ExcelTemplate")
        {
            if (e.SelectedChoiceActionItem.Data is IModelImporting importingModel)
            {
                ExportExcelTemplate(importingModel);
            }
        }
    }
}
